package com.cictec.middleware.core.service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.cictec.middleware.commons.cache.ecache.EHCacheUtils;
import com.cictec.middleware.commons.utils.Constants;
import com.cictec.middleware.commons.utils.DateUtils;
import com.cictec.middleware.commons.utils.PMSUtils;
import com.cictec.middleware.core.entity.BusLine;
import com.cictec.middleware.core.entity.BusSchedule;
import com.cictec.middleware.core.entity.DeparterSchedule;
import com.cictec.middleware.core.mapper.BusScheduleMapper;
import com.cictec.middleware.core.mapper.DeparterScheduleMapper;

import tk.mybatis.mapper.entity.Example;

/**
 * 调度时刻服务
 * 
 * @author ql
 *
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
@Service
public class ScheduleService {

	private static Logger logger = LoggerFactory.getLogger(ScheduleService.class);
	@Autowired
	private DeparterScheduleMapper departerScheduleMapper;
	@Autowired
	private BusScheduleMapper busScheduleMapper;
	@Autowired
	private BusLineService busLineService;

	private static String BUS_SCHECULE_TABLE = "bus-schedule-table";// 新增新增趟次标识
	/**
	 * 系统新增趟次标识
	 */
	private static String systemMark = "[system]";// 新增新增趟次标识

	
	@PostConstruct
	public void init() {
		// System.out.println("注册 BusMileageEngine 到 TimeEventBus");
//		logger.info("【ScheduleService】 加载 {} 发车时刻", DateUtils.formatDate(new Date()));
//		loadLinesSchedule();
	}
	
	/**
	 * 【加载】线路当天的发车时刻到缓存,默认为当天
	 */
	public void loadLinesSchedule(){
		loadLinesSchedule(DateUtils.formatDate(new Date()));
	}
	
	/**
	 * 【加载】线路当天的发车时刻到缓存
	 * @param date 指定日期 yyyy-MM-dd
	 */
	public void loadLinesSchedule(String date){
		
		logger.error("【ScheduleService】加载 {} 的发车时刻", date);
		
		// 查询指定日期所有发车时刻
		Map parMap = new HashMap();
		parMap.put("bs_date", date);
		List<DeparterSchedule>  scheduleList = selectBusRunScheduleDayList(parMap);

		ScheduleDayTable table = new ScheduleDayTable(); 
		table.setDate(date);
		
		for (DeparterSchedule ds : scheduleList) {
			
			List<DeparterSchedule> ls = table.getLineSchedule(ds.getLineUuid());
			if(ls == null){
				ls = Collections.synchronizedList(new ArrayList<DeparterSchedule>());
//				ls = new ArrayList<DeparterSchedule>();
				table.setLineSchedule(ds.getLineUuid(), ls);
			}
			ls.add(ds);
		}
		
		EHCacheUtils.setValue(BUS_SCHECULE_TABLE, date, table);
	}
	
	/**
	 * 【重新加载】更新线路的发车时刻表到内存，默认为当天
	 * @param lineUuid
	 */
	public void reloadLineSchedule(String lineUuid){
		
		reloadLineSchedule(DateUtils.formatDate(new Date()), lineUuid);
	}
	
	/**
	 * 【重新加载】更新线路的发车时刻表到内存
	 * @param lineUuid 线路
	 * @param date	   日期 yyyy-MM-dd
	 */
	public void reloadLineSchedule(String date, String lineUuid){
		Map parMap = new HashMap();
		parMap.put("line_uuid", lineUuid);
		parMap.put("bs_date", date);
		List<DeparterSchedule>  scheduleList = selectBusRunScheduleDayList(parMap);
		List<DeparterSchedule> syncDss =  Collections.synchronizedList(new ArrayList<DeparterSchedule>(scheduleList));
		
		ScheduleDayTable table = getScheduleTable(date);
		
		table.getLineSchedules().put(lineUuid, syncDss);
		EHCacheUtils.setValue(BUS_SCHECULE_TABLE, date, table);
		
		if(logger.isInfoEnabled()){
			BusLine line = busLineService.getLineByLineUuid(lineUuid);
			logger.info("重新加载线路 {} 的时刻表 ",line.getLineName());
			
		}
	}
	
	/**
	 * 根据条件，查询当天发车时刻
	 * @param params
	 * @return
	 */
	public List<DeparterSchedule> selectBusRunScheduleDayList(Map params){
		return departerScheduleMapper.queryBusRunScheduleDayList(params);
	}
	
	/**
	 * 删除指定日期时刻表
	 * @param date
	 */
	public void clearScheduleTable(String date){
		logger.debug("【ScheduleService】删除{}日期时刻表缓存", date);
		
		try {
			EHCacheUtils.removeElment(BUS_SCHECULE_TABLE, date);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	private ScheduleDayTable getScheduleTable(String date){
//		return lineSchedules.get(date);
		ScheduleDayTable table = EHCacheUtils.getValue(BUS_SCHECULE_TABLE, date);
		if(table == null){
			loadLinesSchedule(date);
		}
		table = EHCacheUtils.getValue(BUS_SCHECULE_TABLE, date);
		return table;
	}
	
	
	/**
	 * 【缓存】根据线路获取时刻表【当天】
	 * @param lineUuid
	 * @return
	 */
	public List<DeparterSchedule> getScheduleTableByLineUuid(String lineUuid){
		return getScheduleTableByLineUuid(DateUtils.getDate(), lineUuid);
	}
	
	/**
	 * 【缓存】根据线路获取时刻表
	 * @param date
	 * @param lineUuid
	 * @return
	 */
	public List<DeparterSchedule> getScheduleTableByLineUuid(String date, String lineUuid){
		List<DeparterSchedule> dss = getScheduleTable(date).getLineSchedules().get(lineUuid);
		if(dss != null && dss.size() > 0){
			return dss;
		}
		return new ArrayList();
	}
	
	/**
	 * 获取当天车辆所有调度时刻【按照时间顺序】
	 * @param busUuid 指定车辆
	 * @return
	 */
	public List<DeparterSchedule> getScheduleTableByBusUuid(String date, String busUuid){
		
		ScheduleDayTable table = getScheduleTable(date);
		List<DeparterSchedule> rtList = new ArrayList<DeparterSchedule>();
		if(table == null){
			return rtList;
		}
		
		for (String lineUuid : table.getLineSchedules().keySet()) {  
			
			List list = getScheduleTableByBusUuid(date, lineUuid, busUuid);
		  
			if(list.size() > 0){
				rtList.addAll(list);
			}
		}
		
		rtList.sort(new Comparator<DeparterSchedule>() {
			@Override
			public int compare(DeparterSchedule o1, DeparterSchedule o2) {
				
				Date date1 = o1.getDepartureTime();
				Date date2 = o2.getDepartureTime();
				
				return (int) (date1.getTime() - date2.getTime());
			}
		});
		
		return rtList;
	}
	
	/**
	 *  获取当前车辆、线路下所有调度时刻
	 * @param lineUuid	指定线路
	 * @param busUuid	指定车辆
	 * @return	车辆发车时刻
	 */
	public List<DeparterSchedule> getScheduleTableByBusUuid(String date, String lineUuid, String busUuid) {

		List<DeparterSchedule> rtList = new ArrayList<DeparterSchedule>();
		ScheduleDayTable table = getScheduleTable(date);
		if (table == null) {
			return rtList;
		}
		List<DeparterSchedule> dss = table.getLineSchedules().get(lineUuid);

		if (dss != null) {

			for (DeparterSchedule departerSchedule : dss) {
				if (busUuid.equals(departerSchedule.getBrsdBusUuid())) {
					rtList.add(departerSchedule);
				}
			}
		}

		return rtList;
	}
	
	/**
	 * 获取指定车辆、线路的所有趟次
	 * @param date
	 * @param lineUuid
	 * @param lineType
	 * @param busUuid
	 * @param isPlan	是否是计划趟次
	 * @return
	 */
	public List<DeparterSchedule> getScheduleTableByBusUuid(String date, String lineUuid, String lineType, String busUuid, boolean isPlan) {
		ScheduleDayTable table = getScheduleTable(date);
		if (table == null) {
			return new ArrayList();
		}

		List<DeparterSchedule> dss = table.getLineSchedules().get(lineUuid);

		List<DeparterSchedule> list = new ArrayList<DeparterSchedule>();
		if (dss != null) {
			for (DeparterSchedule d : dss) {

				if (busUuid.equals(d.getBrsdBusUuid()) && (busUuid.equals(d.getBrsdBusUuid()))
						&& (lineType == null ? true : lineType.equals(d.getBrsdType()))) {
					if (isPlan) {
						if (PMSUtils.isEmpty(d.getBrsdRemarks())) {
							list.add(d);
						} else {
							if (d.getBrsdRemarks().indexOf(systemMark) == -1) {
								list.add(d);
							}
						}
					} else {
						list.add(d);
					}
				}
			}
		}

		return list;
	}
	
	/**
	 * 获取线路车辆发车时刻
	 * 
	 * @param lineUuid
	 * @param lineType
	 * @param busUuid
	 * @param currentTime
	 * @param nearestScheduleThreshold
	 *            防止首发站发车，反复进出站造成的抖动,设置的时间误差范围【单位：秒】
	 * @param onlyNotDeparture
	 *            true:在未发车的时刻中查询， false: 忽略是否已发车判定
	 * @return
	 */
	public DeparterSchedule getDeparterSchedule(String lineUuid, String lineType, String busUuid, Date currentTime, int nearestScheduleThreshold, boolean onlyNotDeparture) {
		
		String date = DateUtils.formatDate(currentTime);
		ScheduleDayTable table = getScheduleTable(date);
		if(table == null){
			return null;
		}
		
		List<DeparterSchedule> dss = table.getLineSchedules().get(lineUuid);
		if (dss == null) {
			return null;
		}
		DeparterSchedule currentDeparterSchedule = null;
		long offset = Long.MAX_VALUE;

		synchronized (dss) {
			for (DeparterSchedule ds : dss) {
				Date departerTime = ds.getDepartureTime();
				if(departerTime != null){
					long tempOffset = Math.abs(currentTime.getTime() - departerTime.getTime());
					
					if (busUuid.equals(ds.getBrsdBusUuid())
							&& (lineType == null ? true : lineType.equals(ds.getBrsdType()))
							&& (onlyNotDeparture ? ds.getBrsdDepartureFlag() == Constants.VAL_SCHEDULE_DEPARTURE_FLAG_NOT_DEPARTURE : true)
							&& tempOffset < offset) {
//					System.out.println(tempOffset + "\t" + ds.getBrsdDepartureTime());
						offset = tempOffset;
						currentDeparterSchedule = ds;
					}
				}
			}
		}

		if (nearestScheduleThreshold <= 0 || offset < nearestScheduleThreshold * 60 * 1000) {
			return currentDeparterSchedule;
		} else {
			return null;
		}
	}

	/**
	 * 获取最近的一个未开始执行的发车时刻
	 * 
	 * @param lineUuid
	 * @param lineType 为null时，表示不区分上下行
	 * @param busUuid
	 * @param currentTime
	 * @return
	 */
	public DeparterSchedule getDeparterScheduleNearestNotStart(String lineUuid, String lineType, String busUuid, Date currentTime) {
		return getDeparterSchedule(lineUuid, lineType, busUuid, currentTime, 0, true);
	}


	/**
	 * 获取所有线路中当前车辆时间最近的发车时刻
	 * @param busUuid
	 * @param currentTime
	 * @param nearestScheduleThreshold
	 * @param onlyNotDeparture
	 * @return
	 */
	public DeparterSchedule getDeparterScheduleNearestInAllLine(String busUuid, Date currentTime, int nearestScheduleThreshold, boolean onlyNotDeparture) {
		
		String date = DateUtils.formatDate(currentTime);
		
		ScheduleDayTable table = getScheduleTable(date);
		if(table == null){
			return null;
		}
		
		Map<String, List<DeparterSchedule>> scheduleMap = table.getLineSchedules();
		
		List<DeparterSchedule> dss = new ArrayList<DeparterSchedule>();
		for (String _lineUuid : scheduleMap.keySet()) {
			DeparterSchedule ds = getDeparterScheduleNearestNotStart(_lineUuid, null, busUuid, currentTime);
			if(ds != null){
				dss.add(ds);
			}
		}
		
		dss.sort(new Comparator<DeparterSchedule>() {
			@Override
			public int compare(DeparterSchedule o1, DeparterSchedule o2) {
				
				Date date1 = o1.getDepartureTime();
				Date date2 = o2.getDepartureTime();
				
				return (int) (date1.getTime() - date2.getTime());
			}
		});
		
		DeparterSchedule currentDeparterSchedule = null;
		long offset = Long.MAX_VALUE;
		for (DeparterSchedule ds : dss) {
			Date departerTime = ds.getDepartureTime();
			
			if(departerTime != null){
				long tempOffset = Math.abs(currentTime.getTime() - departerTime.getTime());
				
				if (busUuid.equals(ds.getBrsdBusUuid())
//						&& (lineType == null ? true : lineType.equals(ds.getBrsdType()))
						&& (onlyNotDeparture ? ds.getBrsdDepartureFlag() == Constants.VAL_SCHEDULE_DEPARTURE_FLAG_NOT_DEPARTURE : true)
						&& tempOffset < offset
					){
					offset = tempOffset;
					currentDeparterSchedule = ds;
				}
			}
		}
		
		if (nearestScheduleThreshold <= 0 || offset < nearestScheduleThreshold * 60 * 1000) {
			return currentDeparterSchedule;
		} else {
			return null;
		}
	}


	/**
	 * 根据发车时刻，查询前一个发车时刻。班次相同，趟次减一。
	 * 
	 * @param ds
	 * @return
	 */
	public DeparterSchedule getDepartureSchedulePre(DeparterSchedule ds) {
		
		String date = DateUtils.formatDate(ds.getDepartureTime());
		ScheduleDayTable table = getScheduleTable(date);
		if(table == null){
			return null;
		}
		List<DeparterSchedule> dss = table.getLineSchedules().get(ds.getLineUuid());
		
		DeparterSchedule currentDeparterSchedule = null;
		synchronized (dss) {
			for (DeparterSchedule d : dss) {
				if (ds.getBrsdShift() == d.getBrsdShift() && d.getBrsdTrip() == ds.getBrsdTrip() - 1) {
					currentDeparterSchedule = d;
				}
			}
		}
		return currentDeparterSchedule;
	}
	
	/**
	 * 根据发车时刻，查询后一个发车时刻。班次相同，趟次减一。
	 * 
	 * @param ds
	 * @return
	 */
	public DeparterSchedule getDepartureScheduleAfter(DeparterSchedule ds) {
		String date = DateUtils.formatDate(ds.getDepartureTime());
		ScheduleDayTable table = getScheduleTable(date);
		if(table == null){
			return null;
		}
		List<DeparterSchedule> dss = table.getLineSchedules().get(ds.getLineUuid());
		
		DeparterSchedule currentDeparterSchedule = null;
		synchronized (dss) {
			for (DeparterSchedule d : dss) {
				if (ds.getBrsdShift() == d.getBrsdShift() && d.getBrsdTrip() == ds.getBrsdTrip() + 1) {
					currentDeparterSchedule = d;
				}
			}
		}
		return currentDeparterSchedule;
	}


	/**
	 * 获取给定时间之后的下一个发车时刻。【未发车】【当前时间提前15分钟之后的第一个发车时刻】
	 * @param lineUuid
	 * @param busUuid
	 * @param time
	 * @return
	 */
	public DeparterSchedule getDeparterScheduleNext(Date time, String lineUuid, String busUuid) {
		if (lineUuid == null) {
			return null;
		}

		String date = DateUtils.formatDate(time);
		ScheduleDayTable table = getScheduleTable(date);
		if (table == null) {
			return null;
		}
		
		List<DeparterSchedule> dss = table.getLineSchedules().get(lineUuid);
		
		if (dss == null) {
			return null;
		}
		
		DeparterSchedule nextDs = null;
		synchronized (dss) {
			for (DeparterSchedule d : dss) {
				if (!PMSUtils.isEmpty(d.getBrsdBusUuid()) && d.getBrsdBusUuid().equals(busUuid)
						&& d.getDepartureTime() != null && d.getDepartureTime().getTime() > (time.getTime() - 15 * 60 * 1000)) {
					if (d.getBrsdDepartureFlag() == Constants.VAL_SCHEDULE_DEPARTURE_FLAG_DEPARTURED) {
						nextDs = null;
					} else {
						if (nextDs == null) {
							nextDs = d;
						}
					}
				}
			}
		}

		return nextDs;

	}
	
	/**
	 * 获取指定发车时刻的下一个发车时刻。如果指定了线路，返回指定线路类型的下一个发车时刻
	 * @param currentSchedule
	 * @param lineType 如果为null，不分上下行取下一个趟次
	 * @return
	 */
	public DeparterSchedule getDeparterScheduleNext(DeparterSchedule currentSchedule, String lineType){
		
		if(currentSchedule == null){
			return null;
		}
		
		String date = DateUtils.formatDate(currentSchedule.getDepartureTime());
		ScheduleDayTable table = getScheduleTable(date);
		if (table == null) {
			return null;
		}
		List<DeparterSchedule> dss = table.getLineSchedules().get(currentSchedule.getLineUuid());

		if (dss == null) {
			return null;
		}
		
		DeparterSchedule nextDs = null;
		synchronized (dss) {
			for (DeparterSchedule d : dss) {
				if (!PMSUtils.isEmpty(d.getBrsdBusUuid()) 
						&& d.getBrsdBusUuid().equals(currentSchedule.getBrsdBusUuid())
						&& d.getDepartureTime().getTime() > currentSchedule.getDepartureTime().getTime()
						&& lineType == null ? true : d.getBrsdType().equals(lineType)
						) {
					nextDs = d;
					break;
				}
			}
		}
		return nextDs;
	}

	/**
	 * 获取线路上指定日期车辆的第一个发车时刻。
	 * @param date
	 * @param lineUuid
	 * @param busUuid
	 * @return
	 */
	public DeparterSchedule getDeparterScheduleFirst(Date date, String lineUuid, String busUuid) {
		return getDeparterScheduleFirst(DateUtils.formatDate(date), lineUuid, null, busUuid);
	}

	/**
	 * 获取线路上指定车辆的第一个发车时刻。
	 * @param date
	 * @param lineUuid
	 * @param lineType	可为null，为null时候去当天的第一个时刻，不为null时取指定上下行的第一个时刻
	 * @param busUuid
	 * @return
	 */
	public DeparterSchedule getDeparterScheduleFirst(String date, String lineUuid, String lineType, String busUuid) {
		ScheduleDayTable table = getScheduleTable(date);
		if(table == null){
			return null;
		}
		
		List<DeparterSchedule> dss = table.getLineSchedules().get(lineUuid);

		if (dss != null) {
			synchronized (dss) {
				for (DeparterSchedule d : dss) {

					if (busUuid.equals(d.getBrsdBusUuid()) &&
							(lineType == null ? true : lineType.equals(d.getBrsdType()))) {
						return d;
					}
				}
			}
		}
		return null;
	}
	
	/**
	 * 判定指定日期，车辆是否存在运营时刻
	 * @param date
	 * @param busUuid
	 * @return	true:存在运营时刻表，false:不存在运营时刻表
	 */
	public boolean isScheduleExist(String date, String lineUuid, String lineType, String busUuid){
		
		DeparterSchedule schedule = getDeparterScheduleFirst(date, lineUuid, lineType, busUuid);
		if(schedule != null){
			return true;
		}
		return false;
	}
	/* ***************** ***********************************************************/
	/**
	 * 判定指定日期 该线路是有计划排班
	 * @param date
	 * @param lineUuid
	 * @return	true:存在运营时刻表，false:不存在运营时刻表
	 */
	private boolean isSchedulePlanExist(String date, String lineUuid){
		BusSchedule busSchedule = getBusSchedule(date, lineUuid);
		return busSchedule == null ? false : true;
	}
	
	/**
	 * 获取运营时刻主表
	 * @param date
	 * @param lineUuid
	 * @return
	 */
	private BusSchedule getBusSchedule(String date, String lineUuid){
		String _busLineUuid = getScheduleBusLine(lineUuid).getLineUuid();
		
		BusSchedule busSchedule = new BusSchedule();
		busSchedule.setBsScheduleTime(DateUtils.parseDate(date));
//		busSchedule.setBsLineUuid(lineUuid);
		busSchedule.setBsLineUuid(_busLineUuid); // 获取主线路当天时刻表主表
		List<BusSchedule> list = busScheduleMapper.select(busSchedule);
		
		if (list.size() > 0) {
			return list.get(0);
		}
		
		return null;
	}
	
	/**
	 * 获取线路时刻表 主表线路信息
	 * @return
	 */
	private BusLine getScheduleBusLine(String lineUuid){
		/****** 查询该线路主线路信息 start ************/
		BusLine busLine = busLineService.getLineByLineUuid(lineUuid);
		if(PMSUtils.isNotEmpty(busLine.getParLineUuid()) && !"0".equals(busLine.getParLineUuid())){
//			busLine = busLineService.getLineByLineUuid(busLine.getParLineUuid());// 获取主线路
		}
		return  busLine;
	}

	/**
	 * 更新指定日期、线路、车辆的司机信息
	 * @param date		签到时间
	 * @param lineUuid	
	 * @param busUuid
	 * @param drvUuid
	 */
	public void updateScheduleDriver(Date signTime, String lineUuid, String busUuid, String drvUuid){
		
		String date = DateUtils.formatDate(signTime);
		
		logger.debug("【调度时刻服务】更新时刻表司机：{} busuuid:{}", date, busUuid);
		List<DeparterSchedule> list = getScheduleTableByBusUuid(date, busUuid);
		logger.debug("【调度时刻服务】更新时刻表司机：查询到 {} 该车辆 {} 时刻表总计  {} 条记录", date, busUuid, list.size());
		
		Set<String> lineSet = new HashSet<String>();
		
		String currentDriverUuid = null;
		for (DeparterSchedule departerSchedule : list) {
			if(!lineSet.contains(departerSchedule.getLineUuid())){
				lineSet.add(departerSchedule.getLineUuid());
			}
			
			// 更新大于等于签到时间后的所有车辆
			if(departerSchedule.getDepartureTime() != null
					&& departerSchedule.getDepartureTime().getTime() >= signTime.getTime()){
				
				if (PMSUtils.isNotEmpty(departerSchedule.getBrsdDrvUuid())) {
					if (currentDriverUuid == null) {
						currentDriverUuid = departerSchedule.getBrsdDrvUuid();
					}else if(!currentDriverUuid.equals(PMSUtils.isNull(departerSchedule.getBrsdDrvUuid()))){
						// 按照时间顺序，只更新相同司机段的趟次，这样就可以区分出来一天多个司机在跑了
						// （即：排班表中的不同的司机信息，刷卡也是刷当前时间段内的司机信息更新）
						break;
					}
				}
				
				DeparterSchedule schedule = new DeparterSchedule();
				schedule.setBrsdUuid(departerSchedule.getBrsdUuid());
				schedule.setBrsdDrvUuid(drvUuid);
				schedule.setBrsdLastUpdateTime(signTime);	// 最后更新时间
				departerScheduleMapper.updateByPrimaryKeySelective(schedule);
				
				logger.debug("【调度时刻服务】更新时刻表司机:车辆 {} ==》司机为：{}", busUuid, drvUuid);
			}
		}
		// 更新所有线路下该车时刻表
		for (String upLineUuid : lineSet) {
			reloadLineSchedule(upLineUuid);
			logger.debug("【调度时刻服务】重新加载时刻表缓存: 线路{} 车辆 {} ==》司机为：{}", upLineUuid, busUuid, drvUuid);
		}
	}
	
	/**
	 * 【数据库】更新运营时刻表初始化（中间件为做操作前的状态）
	 * @param date
	 * @param lineUuid
	 * @param busUuid
	 * @param departureFlag
	 */
	public void updateScheduleDepartureFlag(String date, String busUuid) {
		
		List<DeparterSchedule> dss = getScheduleTableByBusUuid(date, busUuid);

		List<DeparterSchedule> updateBrsdUuids = new ArrayList<DeparterSchedule>();
		List<String> lineUuids = new ArrayList<String>();
		
		for (DeparterSchedule departerSchedule : dss) {
			
			if(!lineUuids.contains(departerSchedule.getLineUuid())){
				lineUuids.add(departerSchedule.getLineUuid());
			}
			
			if (!PMSUtils.isEmpty(departerSchedule.getBrsdRemarks()) 
					&& departerSchedule.getBrsdRemarks().indexOf(systemMark) != -1) {
			} else {
				departerSchedule.setBrsdActrualDepartureTime(null);
				departerSchedule.setBrsdActrualArraveTime(null);
				departerSchedule.setBrsdDepartureFlag(0);
				updateBrsdUuids.add(departerSchedule);
			}
		}

		if (updateBrsdUuids.size() > 0) {
			departerScheduleMapper.updateBatchBusRunScheduleDayClear(updateBrsdUuids);
		}
		
		// 删除程序自动添加的趟次start
		Example exampleDelete = new Example(DeparterSchedule.class);
		exampleDelete.createCriteria()
			.andEqualTo("brsdBusUuid", busUuid)
			.andLike("brsdRemarks", systemMark)
			.andGreaterThanOrEqualTo("brsdActrualDepartureTime", DateUtils.getStartDateTime(date))
			.andLessThanOrEqualTo("brsdActrualDepartureTime", DateUtils.getEndDateTime(date));
		departerScheduleMapper.deleteByExample(exampleDelete);
		// 删除程序自动添加的趟次end
		
		
		for (String lineUuid : lineUuids) {
			reloadLineSchedule(date, lineUuid);
		}
	}
	
	
	public void updateBusSchedule(String lineUuid, String lineType, String busUuid, String drvUuid, Date actStartTime, Date actArraveTime){
		String date = DateUtils.formatDate(actStartTime);
		
		if(isSchedulePlanExist(date, lineUuid)){
			// 存在运营时刻主表
			
			if(isScheduleExist(date, lineUuid, lineType, busUuid)){
				
				// 存在该车辆上下行时刻表
				DeparterSchedule ds = getDeparterScheduleNearestNotStart(lineUuid, lineType, busUuid, actStartTime);
//				DeparterSchedule ds = getDeparterSchedule(lineUuid, lineType, busUuid, actStartTime, 0, false);
				if(ds != null
						&& ds.getDepartureTime().getTime() <= actArraveTime.getTime()	// 防止结束时间大于开始时间
						){
					logger.debug("【ScheduleService】更新时刻表趟次信息,lineUuid {} 存在 车辆 {} 运营时刻表，趟次直接更新");
					//【存在，更新】
					updateScheduleTripStartOrEndTime(ds.getBrsdUuid(), actStartTime, actArraveTime);
				}else{
					//【不存在，新增】
					DeparterSchedule first = getDeparterScheduleFirst(date, lineUuid, lineType, busUuid);
//					int trip = getLastTrip(date, lineUuid, lineType, busUuid) + 1;
					
					// 新建子表
					DeparterSchedule departerSchedule = insertBusScheduleRun(first.getBrsdBrsUuid(), lineUuid, busUuid, drvUuid, actStartTime, actArraveTime, lineType, null, null);

					logger.debug("【ScheduleService】更新时刻表趟次信息，lineUuid:{} 不存在该车辆 {} 运营时刻表,新增该车班次、趟次：{}", lineUuid, busUuid, JSON.toJSONString(departerSchedule));
				}
				
			}else{
				
				// 存在该车辆上下行时刻表
				String brsUuid = getBusSchedule(date, lineUuid).getBsUuid();
//				DeparterSchedule firstDs = getDeparterScheduleFirst(date, lineUuid, busUuid);
				/* 
				 * 【存在主表，但没有排该车辆】
				 * 	1、获取班次号
				 * 
				 */
//				int shift = firstDs == null ? getLastShiftByLineUuid(date, lineUuid) + 1 : firstDs.getBrsdShift();
//				int trip = getLastTrip(date, lineUuid, lineType, busUuid);
//				int trip = 1;
				
				
				// 新建子表
				DeparterSchedule departerSchedule = insertBusScheduleRun(brsUuid, lineUuid, busUuid, drvUuid, actStartTime, actArraveTime, lineType, null, null);
				
				logger.debug("【ScheduleService】更新时刻表趟次信息，lineUuid:{} 不存在该车辆 {} 运营时刻表,新增该车班次、趟次：{}", lineUuid, busUuid, JSON.toJSONString(departerSchedule));
			}
			
		}else{
			// 不存在运营时刻主表
			
			// 新建主表、子表
			// 新建主表
			BusSchedule busSchedule = insertBusScheduleMain(lineUuid, actStartTime);
			
			// 新建子表
			DeparterSchedule departerSchedule = insertBusScheduleRun(busSchedule.getBsUuid(), lineUuid, busUuid, drvUuid, actStartTime, actArraveTime, lineType, null, null);
			logger.debug("【ScheduleService】更新时刻表趟次信息: lineUuid {} 不存在 车辆 {} 运营时刻表，新增运营时刻主表，日运营时刻表:{}", lineUuid, busUuid, JSON.toJSONString(departerSchedule));
		}
		
		this.reloadLineSchedule(date, lineUuid);
		
	}
	
	/**
	 * 更新指定趟次实际开始（结束时间）
	 * @param brsdUuid
	 * @param startTime
	 * @param endTime
	 */
	public void updateScheduleTripStartOrEndTime(String brsdUuid, Date startTime, Date endTime){
		DeparterSchedule schedule = new DeparterSchedule();
		schedule.setBrsdUuid(brsdUuid);
		schedule.setBrsdLastUpdateTime(new Date());
		schedule.setBrsdDepartureFlag(1);
		if(startTime != null){
			schedule.setBrsdActrualDepartureTime(startTime);
		}
		if(endTime != null){
			schedule.setBrsdArraveFlag(1);
			schedule.setBrsdActrualArraveTime(endTime);
		}
		departerScheduleMapper.updateByPrimaryKeySelective(schedule);
	}
	
	/**
	 * 新增运营时刻主表
	 * @param bsUuid
	 * @param lineUuid
	 * @param startTime
	 * @return
	 */
	private BusSchedule insertBusScheduleMain(String lineUuid, Date startTime) {
		// 不存在运营时刻主表
//		BusLine busLine = busLineService.getLineByLineUuid(lineUuid);
		BusLine busLine = getScheduleBusLine(lineUuid);	// 获取线路时刻表 主表线路信息

		// 新建主表
		BusSchedule busSchedule = new BusSchedule();
		busSchedule.setBsUuid(PMSUtils.getUUID());
		busSchedule.setBsOrgUuid(busLine.getLineOrgUuid());
		busSchedule.setBsLineUuid(lineUuid);
		busSchedule.setBsScheduleTime(DateUtils.getStartDateTime(startTime));

		busSchedule.setBsExchangedate(1);
		busSchedule.setBsType("0");
		busSchedule.setBsClassRepeatDays(0);
		// busSchedule.setBsBusClassRepeatDays(0);
		busSchedule.setBsDrvRepeatDays(0);
		busSchedule.setBsRepeatDays(0);
		busSchedule.setBsDropFlag("0");
		busSchedule.setBsCreateTime(new Date());
		busScheduleMapper.insertSelective(busSchedule);
		return busSchedule;
	}

	/**
	 * 新增运营时刻子表（日运营时刻表）
	 */
	private DeparterSchedule insertBusScheduleRun(String bsUuid, String lineUuid, String busUuid, String drvUuid, Date actStartTime, Date actArraveTime, String lineType, Integer shift, Integer trip){
		DeparterSchedule departerSchedule = new DeparterSchedule();
		departerSchedule.setBrsdUuid(PMSUtils.getUUID());
		departerSchedule.setBrsdBrsUuid(bsUuid);
		departerSchedule.setBrsdBusUuid(busUuid);
		departerSchedule.setBrsdDrvUuid(drvUuid);
		departerSchedule.setDepartureTime(actStartTime);
		departerSchedule.setBrsdActrualDepartureTime(actStartTime);
		departerSchedule.setBrsdActrualArraveTime(actArraveTime);
		departerSchedule.setBrsdBranchLineUuid(lineUuid);		// 实际趟次线路信息
		
//		departerSchedule.setLineUuid(lineUuid);
		departerSchedule.setBrsdType(lineType);
//		departerSchedule.setBrsdShift(1);
//		departerSchedule.setBrsdTrip(1);
		departerSchedule.setBrsdShift(shift == null ? 0 : shift);
		departerSchedule.setBrsdTrip(trip == null ? 0 : trip);
		departerSchedule.setBrsdIsdel(0);
		departerSchedule.setBrsdLastUpdateTime(new Date());
		departerSchedule.setBrsdDepartureFlag(1);	// 是否以发车
//		departerSchedule.setBrsdArraveFlag(1);		//是否已到达最后一站
		departerSchedule.setBrsdRemarks(systemMark);// 系统添加标识
		
		departerScheduleMapper.insertSelective(departerSchedule);
		return departerSchedule;
	}

	/**
	 * 获取指定日期指定线路的实际运营时刻表的最大班次号
	 * @param date
	 * @param lineUuid
	 * @return
	 */
	private Integer getLastShiftByLineUuid(String date, String lineUuid){
		int shift = 0;
		
		List<DeparterSchedule> list= getScheduleTableByLineUuid(date, lineUuid);
		for (DeparterSchedule departerSchedule : list) {
			if(departerSchedule.getBrsdShift() > shift){
				shift = departerSchedule.getBrsdShift();
			}
		}
		return shift;
	}
	
	/**
	 * 获取指定日期指定线路指定上下行指定车辆的时刻表最大排班趟次
	 * @param date
	 * @param lineUuid
	 * @param lineType
	 * @param busUuid
	 * @return
	 */
	private Integer getLastTrip(String date, String lineUuid, String lineType, String busUuid) {
		int trip = 0;

		List<DeparterSchedule> dss = getScheduleTableByBusUuid(date, lineUuid, busUuid);

		for (DeparterSchedule d : dss) {

			if (busUuid.equals(d.getBrsdBusUuid()) 
					&& lineType.equals(d.getBrsdType())
					) {
				
				if(d.getBrsdTrip() > trip){
					trip = d.getBrsdTrip();
				}
			}
		}

		return trip;
	}
	
	
}

/**
 * 调度时刻表
 * 
 * @author ql
 *
 */
class ScheduleDayTable implements Serializable {
	private static final long serialVersionUID = -1312854927347215643L;

	/**
	 * 时刻表日期
	 */
	private String date;

	/** 对应日期时刻表 */
//	private Map<String, List<DeparterSchedule>> lineSchedules = new ConcurrentHashMap<String, List<DeparterSchedule>>();
	private Map<String, List<DeparterSchedule>> lineSchedules = new HashMap<String, List<DeparterSchedule>>();

	/**
	 * 设置线路时刻表
	 * 
	 * @param lineUuid
	 * @param scheduleList
	 */
	public void setLineSchedule(String lineUuid, List<DeparterSchedule> scheduleList) {
		lineSchedules.put(lineUuid, scheduleList);
	}

	/**
	 * 获取指定线路的时刻表
	 * 
	 * @param lineUuid
	 * @return
	 */
	public List<DeparterSchedule> getLineSchedule(String lineUuid) {
		return lineSchedules.get(lineUuid);
	}

	public String getDate() {
		return date;
	}

	public void setDate(String date) {
		this.date = date;
	}

	public Map<String, List<DeparterSchedule>> getLineSchedules() {
		return lineSchedules;
	}

	public void setLineSchedules(Map<String, List<DeparterSchedule>> lineSchedules) {
		this.lineSchedules = lineSchedules;
	}

}
